home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / kick.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  6KB  |  239 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: kick.c,v 1.27 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include "opennap.h"
  8. #include "debug.h"
  9.  
  10. int
  11. is_chanop (CHANNEL * chan, USER * user)
  12. {
  13.     LIST   *list;
  14.     CHANUSER *chanUser;
  15.  
  16.     for (list = chan->users; list; list = list->next)
  17.     {
  18.     chanUser = list->data;
  19.     ASSERT (chanUser->magic == MAGIC_CHANUSER);
  20.     if (chanUser->user == user)
  21.         return (chanUser->flags & ON_CHANNEL_OPERATOR);
  22.     }
  23.     return 0;
  24. }
  25.  
  26. void
  27. sync_channel_user (CONNECTION * con, CHANNEL * chan, CHANUSER * chanUser)
  28. {
  29.     ASSERT (chan->local == 0);
  30.  
  31.     /* have to correct for desync */
  32.     send_cmd (con, MSG_CLIENT_JOIN, ":%s %s", chanUser->user->nick,
  33.           chan->name);
  34.  
  35.     /* restore channel flags */
  36.     if (chanUser->flags & ON_CHANNEL_OPERATOR)
  37.     send_cmd (con, MSG_CLIENT_OP, ":%s %s %s :%u",
  38.           Server_Name, chan->name, chanUser->user->nick,
  39.           chan->timestamp);
  40.     if (chanUser->flags & ON_CHANNEL_VOICE)
  41.     send_cmd (con, MSG_CLIENT_CHANNEL_VOICE, ":%s %s %s :%u",
  42.           Server_Name, chan->name, chanUser->user->nick,
  43.           chan->timestamp);
  44.     if (chanUser->flags & ON_CHANNEL_MUZZLED)
  45.     send_cmd (con, MSG_CLIENT_CHANNEL_MUZZLE, ":%s %s %s \"\" %u",
  46.           Server_Name, chan->name, chanUser->user->nick,
  47.           chan->timestamp);
  48. }
  49.  
  50. /* 10202 [ :<sender> ] <channel> <user> [ "<reason>" ] */
  51. HANDLER (kick)
  52. {
  53.     char   *av[3];
  54.     char   *senderName;
  55.     int     ac = -1;
  56.     USER   *user, *sender;
  57.     CHANNEL *chan;
  58.     CHANUSER *chanUser;
  59.  
  60.     (void) len;
  61.     ASSERT (validate_connection (con));
  62.     if (pop_user_server (con, tag, &pkt, &senderName, &sender))
  63.     return;
  64.     if (pkt)
  65.     ac = split_line (av, FIELDS (av), pkt);
  66.     if (ac < 2)
  67.     {
  68.     unparsable (con);
  69.     return;
  70.     }
  71.     chan = hash_lookup (Channels, av[0]);
  72.     if (!chan)
  73.     {
  74.     nosuchchannel (con);
  75.     return;
  76.     }
  77.     if (chan->local && ISSERVER (con))
  78.     {
  79.     log ("kick: server %s accessed local channel %s", con->host,
  80.          chan->name);
  81.     return;
  82.     }
  83.     user = hash_lookup (Users, av[1]);
  84.     if (!user)
  85.     {
  86.     if (ISUSER (con))
  87.         send_cmd (con, MSG_SERVER_NOSUCH,
  88.               "channel kick failed: no such user");
  89.     return;
  90.     }
  91.  
  92.     if (sender && sender->level < LEVEL_MODERATOR)
  93.     {
  94.     if (list_find (sender->channels, chan) == 0)
  95.     {
  96.         if (ISUSER (con))
  97.         send_cmd (con, MSG_SERVER_NOSUCH,
  98.               "channel kick failed: you are not on that channel");
  99.         return;
  100.     }
  101.     else if (!is_chanop (chan, sender))
  102.     {
  103.         if (ISUSER (con))
  104.         send_cmd (con, MSG_SERVER_NOSUCH,
  105.               "channel kick failed: you are not channel operator");
  106.         return;
  107.     }
  108.     }
  109.  
  110.     /* check if the target user is on the given channel */
  111.     chanUser = find_chanuser (chan->users, user);
  112.  
  113.     if (!chanUser)
  114.     {
  115.     if (ISUSER (con))
  116.         send_cmd (con, MSG_SERVER_NOSUCH,
  117.               "channel kick failed: user is not on that channel");
  118.     return;
  119.     }
  120.  
  121.     if (ac > 2)
  122.     truncate_reason (av[2]);
  123.  
  124.     if (!chan->local)
  125.     pass_message_args (con, tag, ":%s %s %s \"%s\"", senderName,
  126.                chan->name, user->nick, (ac > 2) ? av[2] : "");
  127.  
  128.     if (ISUSER (user->con))
  129.     {
  130.     char   *who;
  131.  
  132.     if (sender && sender->cloaked && user->level < LEVEL_MODERATOR)
  133.         who = "Operator";
  134.     else
  135.         who = senderName;
  136.  
  137.     send_cmd (user->con, MSG_CLIENT_PART, chan->name);
  138.     send_cmd (user->con, MSG_SERVER_NOSUCH,
  139.           "You were kicked from channel %s by%s %s: %s",
  140.           chan->name, !sender ? "server " : "",
  141.           who, ac > 2 ? av[2] : "");
  142.     }
  143.  
  144.     user->channels = list_delete (user->channels, chan);
  145.  
  146.     notify_ops (chan, "%s%s kicked %s out of channel %s: %s",
  147.         !sender ? "Server " : "",
  148.         senderName, user->nick, chan->name, ac > 2 ? av[2] : "");
  149.  
  150.     /* has to come after the notify_ops() since it uses chan->name and
  151.        chan may disappear if there are no users left
  152.        Greg Prosser <greg@snickers.org> */
  153.     part_channel (chan, user);
  154. }
  155.  
  156. /* 820 [ :<sender> ] <channel> ["reason"] */
  157. HANDLER (clear_channel)
  158. {
  159.     CHANNEL *chan;
  160.     CHANUSER *chanUser;
  161.     USER   *sender;
  162.     LIST   *list;
  163.     char   *chanName, *senderName;
  164.  
  165.     (void) len;
  166.     ASSERT (validate_connection (con));
  167.     if (pop_user_server (con, tag, &pkt, &senderName, &sender))
  168.     return;
  169.     chanName = next_arg (&pkt);
  170.     if (!chanName)
  171.     {
  172.     unparsable (con);
  173.     return;
  174.     }
  175.     chan = hash_lookup (Channels, chanName);
  176.     if (!chan)
  177.     {
  178.     nosuchchannel (con);
  179.     return;
  180.     }
  181.     if (!sender)
  182.     {
  183.     log ("clear_channel: error, server %s tried to clear channel %s",
  184.          con->host, chanName);
  185.     return;
  186.     }
  187.  
  188.     if (chan->local && ISSERVER (con))
  189.     {
  190.     log ("clear_channel: server %s cleared local channel %s",
  191.          con->host, chan->name);
  192.     return;
  193.     }
  194.  
  195.     if (sender->level < LEVEL_MODERATOR && !is_chanop (chan, sender))
  196.     {
  197.     if (ISUSER (con))
  198.         send_cmd (con, MSG_SERVER_NOSUCH,
  199.             "channel clear failed: not channel operator");
  200.     return;
  201.     }
  202.  
  203.     if (pkt)
  204.     truncate_reason (pkt);
  205.     if (!chan->local)
  206.     pass_message_args (con, tag, ":%s %s %s", sender->nick, chan->name,
  207.                NONULL (pkt));
  208.     notify_ops (chan, "%s cleared channel %s: %s", sender->nick,
  209.         chan->name, NONULL (pkt));
  210.     list = chan->users;
  211.     while (list)
  212.     {
  213.     ASSERT (VALID_LEN (list, sizeof (LIST)));
  214.     chanUser = list->data;
  215.     ASSERT (chanUser->magic == MAGIC_CHANUSER);
  216.     /* part_channel() may free the current `list' pointer so we advance
  217.        it here prior to calling it */
  218.     list = list->next;
  219.     /* this used to avoid kicking users of a higher level, but that
  220.      * lead to many desyncs.  just make it all all-or-nothing event.
  221.      * mods+ can always bypass any channel restrictions anyway
  222.      */
  223.     if (chanUser->user != sender)
  224.     {
  225.         chanUser->user->channels =
  226.         list_delete (chanUser->user->channels, chan);
  227.         if (ISUSER (chanUser->user->con))
  228.         {
  229.         send_cmd (chanUser->user->con, MSG_CLIENT_PART, "%s",
  230.               chan->name);
  231.         send_cmd (chanUser->user->con, MSG_SERVER_NOSUCH,
  232.               "%s cleared channel %s: %s", sender->nick,
  233.               chan->name, NONULL (pkt));
  234.         }
  235.         part_channel (chan, chanUser->user);
  236.     }
  237.     }
  238. }
  239.